SUIPatternLibrary.Model = (function($){
var
    observable = {},
    
    pattern = undefined,
    searchEngines = undefined,

    activeTab = undefined,

    enginesLoaded = false,
    patternsLoaded = false,
	
	active = false,
    
    init = function(){
        fetchPatterns();
        fetchEngines();
        initActiveTab();
    },

    checkLoaded = function(){
        if(enginesLoaded && patternsLoaded){
            $(observable).trigger("ready");
        }
    },

    isReady = function(){
        return enginesLoaded && patternsLoaded;
    },
	
	isActive = function(){
		return active;
	},
	
	setActive = function(bool){
		active = bool;
	},

    initActiveTab = function(){
        if(chrome.tabs){
            chrome.tabs.onActiveChanged.addListener(function(){
                fetchActiveTab();
            });
            fetchActiveTab();
        }
    },

    getSearchEngines = function(){
        return searchEngines;
    },

    getEngineByName = function(engineName){
        for(var i = 0, max = searchEngines.length; i < max; i++){
            if (searchEngines[i].name == engineName){
                return searchEngines[i];
            }
        }
        return undefined;
    },

    getPattern = function(){
        return pattern;
    },

    getPatternNames = function(){
        var names = [];
        for(var i = 0, max = pattern.length; i < max; i++){
            names.push(pattern[i]["name"]);
        }
        return names;
    },

    getEngineNames = function(){
        var names = [];
        for(var i = 0, max = searchEngines.length; i < max; i++){
            names.push(searchEngines[i]["name"]);
        }
        return names;
    },

    loadEnginePatterns = function(engineName){
        SUIPatternLibrary.Database.selectPatternsForEngine(engineName, function(pattern){
            for(var i = 0, max = searchEngines.length; i < max; i++){
                if(searchEngines[i].name == engineName) {
                    searchEngines[i].pattern = pattern;
                    onEnginePatternsLoaded();
                    break;
                }
            }
        });
    },

    loadPatternEngine = function(patternName){
        SUIPatternLibrary.Database.selectEnginesForPattern(patternName, function(engines){
            for(var i = 0, max = pattern.length; i < max; i++){
                if(pattern[i].name == patternName) {
                    pattern[i].engines = engines;
                    onPatternEnginesLoaded();
                    break;
                }
            }
        });
    },

    loadRelatedPatterns = function(patternName){
        SUIPatternLibrary.Database.selectRelatedPatternsForPattern(patternName, function(related){
            for(var i = 0, max = pattern.length; i < max; i++){
                if(pattern[i].name == patternName) {
                    pattern[i].related = related;
                    break;
                }
            }
        });
    },

    loadPrinciplesForPattern = function(patternName){
        SUIPatternLibrary.Database.selectPrinciplesForPattern(patternName, function(principles){
            for(var i = 0, max = pattern.length; i < max; i++){
                if(pattern[i].name == patternName) {
                    pattern[i].principles = principles;
                    break;
                }
            }
        });
    },

    onPatternEnginesLoaded = function(){
        for(var i = 0, max = pattern.length; i < max; i++){
            if(pattern[i].engines == undefined) return;
        }
        enginesLoaded = true;
        checkLoaded();
        $(observable).trigger("patternsLoaded");
        fetchRelatedPatternsForPattern();
        fetchPrinciplesForPattern();
    },

    onEnginePatternsLoaded = function(){
        for(var i = 0, max = searchEngines.length; i < max; i++){
            if(searchEngines[i].pattern == undefined) return;
        }
        patternsLoaded = true;
        checkLoaded();
        $(observable).trigger("enginesLoaded");
    },

    fetchPatternsForEngines = function(){
        for(var i = 0, max = searchEngines.length; i < max; i++){
            loadEnginePatterns(searchEngines[i].name)
        }
    },

    fetchEnginesForPattern = function(){
        for(var i = 0, max = pattern.length; i < max; i++){
            loadPatternEngine(pattern[i].name)
        }
    },

    fetchRelatedPatternsForPattern = function(){
        for(var i = 0, max = pattern.length; i < max; i++){
            loadRelatedPatterns(pattern[i].name)
        }
    },

    fetchPrinciplesForPattern = function(){
        for(var i = 0, max = pattern.length; i < max; i++){
            loadPrinciplesForPattern(pattern[i].name)
        }
    },

    getPatternByName = function(patternName){
        for(var i = 0, max = pattern.length; i < max; i++){
            if(pattern[i].name == patternName)
                return pattern[i];
        }
        return undefined;
    },

    fetchEngines = function(){
        SUIPatternLibrary.Database.selectEngines(function(engines){
            searchEngines = engines;
            for(var i = 0, max = searchEngines.length; i < max; i++){
                searchEngines[i].pattern = undefined;
            }
            fetchPatternsForEngines();
        });
    },

    fetchPatterns = function(){
        SUIPatternLibrary.Database.selectPatterns(function(_pattern){
            pattern = _pattern;
            for(var i = 0, max = pattern.length; i < max; i++){
                pattern[i].engines = undefined;
            }
            fetchEnginesForPattern();
        });
    },

    getEngineByLocation = function(url){
        var loc = url.split(".")[1].toLowerCase();
        for(var i = 0, max = searchEngines.length; i < max; i++){
            var engineName = searchEngines[i].name.toLowerCase();
            if (engineName == loc){
                return searchEngines[i];
            }
        }
        return undefined;
    },

    fetchActiveTab = function(callback){
        chrome.tabs.getAllInWindow(function(tabs){
            for(var i = 0, max = tabs.length; i < max; i++){
                if(tabs[i].active){
                    activeTab = tabs[i];
                    if(callback) callback(activeTab);
                    return;
                }
            }
        });
    }
    
    return {
        init : init,
        isReady : isReady,
		isActive : isActive,
		setActive : setActive,
        getPattern : getPattern,
        getEngineByName : getEngineByName,
        getPatternByName : getPatternByName,
        getSearchEngines : getSearchEngines,
        getPatternNames : getPatternNames,
        getEngineNames : getEngineNames,
        getEngineByLocation : getEngineByLocation,
        on : function(event, callback){
            $(observable).on(event, callback);
        }
    }
    
}(jQuery));